//+------------------------------------------------------------------+
//|                                                          Wnd.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Rect.h"                          // 矩形/点/尺寸结构（控件布局核心）
#include "Defines.h"                       // 控件常量定义（如状态标志、事件ID等）
#include <Object.h>                        // MQL5 基础对象类（CObject）

class CDragWnd; // 前向声明：拖拽辅助类

//+------------------------------------------------------------------+
//| CWnd 类：MQL5 所有可视化控件的基类                                |
//| 核心能力：封装控件通用属性与行为（布局、状态、事件、鼠标交互等），  |
//|           为所有子类控件（如按钮、编辑框、面板等）提供统一接口，     |
//|           不直接实例化，需通过子类实现具体功能                     |
//| 适用场景：作为自定义控件的父类，提供基础能力支持                   |
//+------------------------------------------------------------------+
class CWnd : public CObject
  {
protected:
   // 控件创建与绑定参数（保护，子类可访问）
   long              m_chart_id;            // 绑定的图表ID（0 表示当前活跃图表）
   int               m_subwin;              // 绑定的子窗口编号（0=主窗口，≥1=指标子窗口）
   string            m_name;                // 控件唯一名称（图表内不可重复）

   // 几何布局参数（保护，子类可修改）
   CRect             m_rect;                // 控件在图表上的矩形区域（位置+尺寸）

   // 标识与状态参数（保护，子类可调整）
   long              m_id;                  // 控件唯一ID（用于区分不同控件）
   int               m_state_flags;         // 状态标志（如启用、可见、激活等，见 WND_STATE_FLAG_*）
   int               m_prop_flags;          // 属性标志（如可拖拽、支持双击等，见 WND_PROP_FLAG_*）

   // 对齐参数（保护，子类可配置）
   int               m_align_flags;         // 对齐方式标志（如靠左、靠下等，见 WND_ALIGN_*）
   int               m_align_left;          // 左对齐偏移量（像素）
   int               m_align_top;           // 上对齐偏移量（像素）
   int               m_align_right;         // 右对齐偏移量（像素）
   int               m_align_bottom;        // 下对齐偏移量（像素）

   // 鼠标状态缓存（保护，子类可读取）
   int               m_mouse_x;             // 最后一次鼠标X坐标（像素）
   int               m_mouse_y;             // 最后一次鼠标Y坐标（像素）
   int               m_mouse_flags;         // 最后一次鼠标按键状态（见 MOUSE_* 常量）
   uint              m_last_click;          // 最后一次点击时间（毫秒，用于判断双击）

   // 拖拽辅助对象（保护，子类可使用）
   CDragWnd         *m_drag_object;         // 拖拽时的辅助对象指针（非空表示正在拖拽）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化控件默认状态
    * @details 初始化绑定参数（无效值）、几何布局（空矩形）、状态标志（默认启用+可见）、
    *          鼠标状态（无效值）、拖拽对象（空指针）等基础属性
    */
                     CWnd(void);

   /**
    * @brief 析构函数：清理控件资源
    * @details 依赖子类重写 Destroy() 释放具体资源，基类仅处理通用清理
    */
                    ~CWnd(void);

   //----------------------------------------------------------------
   // 控件创建与销毁：绑定图表并初始化基础属性
   //----------------------------------------------------------------
   /**
    * @brief 创建控件并绑定到指定图表
    * @param chart [in] 目标图表ID（0 表示当前活跃图表）
    * @param name [in] 控件唯一名称（图表内不可重复）
    * @param subwin [in] 绑定的子窗口编号（0=主窗口，≥1=指标子窗口）
    * @param x1 [in] 左上角X坐标（像素，相对于图表窗口）
    * @param y1 [in] 左上角Y坐标（像素）
    * @param x2 [in] 右下角X坐标（像素）
    * @param y2 [in] 右下角Y坐标（像素）
    * @return bool - 创建结果：true=成功（绑定图表+设置初始位置），false=失败
    * @note 子类需重写此方法以创建具体控件（如图表对象、子控件等）
    */
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);

   /**
    * @brief 销毁控件并释放资源
    * @param reason [in] 销毁原因（默认 0，预留参数）
    * @details 子类需重写此方法以释放自身资源（如删除图表对象、子控件等）
    */
   virtual void      Destroy(const int reason=0);

   //----------------------------------------------------------------
   // 事件处理：响应图表与鼠标事件
   //----------------------------------------------------------------
   /**
    * @brief 处理图表事件（如鼠标移动、对象交互等）
    * @param id [in] 事件ID（如 CHARTEVENT_MOUSE_MOVE 表示鼠标移动）
    * @param lparam [in] 长整数参数（事件相关数据，如鼠标X坐标）
    * @param dparam [in] 双精度参数（事件相关数据，如鼠标Y坐标）
    * @param sparam [in] 字符串参数（事件相关数据，如对象名称）
    * @return bool - 处理结果：true=事件已处理，false=未处理（交由父类或系统）
    * @note 基类默认仅处理鼠标移动事件，子类需重写以支持更多事件
    */
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

   /**
    * @brief 处理鼠标事件（封装鼠标坐标与按键状态）
    * @param x [in] 鼠标X坐标（像素，相对于图表窗口）
    * @param y [in] 鼠标Y坐标（像素）
    * @param flags [in] 鼠标按键状态（见 MOUSE_* 常量，如 MOUSE_LEFT 表示左键按下）
    * @return bool - 处理结果：true=事件已处理，false=未处理
    * @note 负责鼠标悬停、点击、拖拽等逻辑的分发，子类可重写以定制鼠标行为
    */
   virtual bool      OnMouseEvent(const int x,const int y,const int flags);

   //----------------------------------------------------------------
   // 控件标识：获取只读属性
   //----------------------------------------------------------------
   /**
    * @brief 获取控件唯一名称
    * @return string - 控件名称（创建时指定）
    */
   string            Name(void)                        const;

   //----------------------------------------------------------------
   // 容器能力：基础接口（子类需重写以支持子控件）
   //----------------------------------------------------------------
   /**
    * @brief 获取子控件数量（基类无容器能力，返回 0）
    * @return int - 子控件数量（默认 0）
    * @note 容器类控件（如 CWndContainer）需重写此方法
    */
   int               ControlsTotal(void)               const;

   /**
    * @brief 获取指定索引的子控件（基类无容器能力，返回 NULL）
    * @param ind [in] 子控件索引（0 开始）
    * @return CWnd* - 子控件指针（默认 NULL）
    * @note 容器类控件（如 CWndContainer）需重写此方法
    */
   CWnd*             Control(const int ind)            const;

   /**
    * @brief 根据ID查找子控件（基类仅检查自身ID）
    * @param id [in] 目标控件ID
    * @return CWnd* - 找到的控件指针（未找到返回 NULL）
    * @note 容器类控件（如 CWndContainer）需重写此方法以遍历子控件
    */
   virtual CWnd*     ControlFind(const long id);

   //----------------------------------------------------------------
   // 几何布局：位置与尺寸操作
   //----------------------------------------------------------------
   /**
    * @brief 获取控件的矩形区域（位置+尺寸）
    * @return CRect - 矩形结构（包含 left/top/right/bottom）
    */
   const CRect       Rect(void)                        const;

   /**
    * @brief 获取控件左边界坐标
    * @return int - 左边界X坐标（像素）
    */
   int               Left(void)                        const;

   /**
    * @brief 设置控件左边界坐标（不改变宽度）
    * @param x [in] 新的左边界X坐标（像素）
    */
   virtual void      Left(const int x);

   /**
    * @brief 获取控件上边界坐标
    * @return int - 上边界Y坐标（像素）
    */
   int               Top(void)                         const;

   /**
    * @brief 设置控件上边界坐标（不改变高度）
    * @param y [in] 新的上边界Y坐标（像素）
    */
   virtual void      Top(const int y);

   /**
    * @brief 获取控件右边界坐标
    * @return int - 右边界X坐标（像素）
    */
   int               Right(void)                       const;

   /**
    * @brief 设置控件右边界坐标（不改变左边界，即调整宽度）
    * @param x [in] 新的右边界X坐标（像素）
    */
   virtual void      Right(const int x);

   /**
    * @brief 获取控件下边界坐标
    * @return int - 下边界Y坐标（像素）
    */
   int               Bottom(void)                      const;

   /**
    * @brief 设置控件下边界坐标（不改变上边界，即调整高度）
    * @param y [in] 新的下边界Y坐标（像素）
    */
   virtual void      Bottom(const int y);

   /**
    * @brief 获取控件宽度
    * @return int - 宽度（像素，right - left）
    */
   int               Width(void)                       const;

   /**
    * @brief 设置控件宽度（保持左边界不变，调整右边界）
    * @param w [in] 目标宽度（像素，≥0）
    * @return bool - 设置结果：true=成功（触发 OnResize()），false=失败
    */
   virtual bool      Width(const int w);

   /**
    * @brief 获取控件高度
    * @return int - 高度（像素，bottom - top）
    */
   int               Height(void)                      const;

   /**
    * @brief 设置控件高度（保持上边界不变，调整下边界）
    * @param h [in] 目标高度（像素，≥0）
    * @return bool - 设置结果：true=成功（触发 OnResize()），false=失败
    */
   virtual bool      Height(const int h);

   /**
    * @brief 获取控件尺寸（宽度+高度）
    * @return CSize - 尺寸结构（包含 cx=宽度, cy=高度）
    */
   CSize             Size(void)                        const;

   /**
    * @brief 设置控件尺寸（保持左上角不变，调整右下角）
    * @param w [in] 目标宽度（像素）
    * @param h [in] 目标高度（像素）
    * @return bool - 设置结果：true=成功（触发 OnResize()），false=失败
    */
   virtual bool      Size(const int w,const int h);

   /**
    * @brief 通过尺寸结构设置控件尺寸
    * @param size [in] 目标尺寸（CSize 结构）
    * @return bool - 设置结果：true=成功（触发 OnResize()），false=失败
    */
   virtual bool      Size(const CSize &size);

   /**
    * @brief 绝对移动控件（将左上角移动到指定坐标，保持尺寸不变）
    * @param x [in] 目标左上角X坐标（像素）
    * @param y [in] 目标左上角Y坐标（像素）
    * @return bool - 移动结果：true=成功（触发 OnMove()），false=失败
    */
   virtual bool      Move(const int x,const int y);

   /**
    * @brief 通过点结构绝对移动控件
    * @param point [in] 目标左上角点（CPoint 结构）
    * @return bool - 移动结果：true=成功（触发 OnMove()），false=失败
    */
   virtual bool      Move(const CPoint &point);

   /**
    * @brief 相对移动控件（从当前位置偏移，保持尺寸不变）
    * @param dx [in] X轴偏移量（像素，正数向右，负数向左）
    * @param dy [in] Y轴偏移量（像素，正数向下，负数向上）
    * @return bool - 移动结果：true=成功（触发 OnMove()），false=失败
    */
   virtual bool      Shift(const int dx,const int dy);

   /**
    * @brief 检查坐标点是否在控件内部（包含边界）
    * @param x [in] 点的X坐标（像素）
    * @param y [in] 点的Y坐标（像素）
    * @return bool - 检查结果：true=点在控件内，false=点在控件外
    */
   bool              Contains(const int x,const int y) const;

   /**
    * @brief 检查另一个控件是否完全在当前控件内部（包含边界）
    * @param control [in] 待检查的控件指针
    * @return bool - 检查结果：true=控件完全在内部，false=否则（含控件为空）
    */
   bool              Contains(CWnd *control) const;

   //----------------------------------------------------------------
   // 对齐配置：设置控件相对于父区域的对齐方式
   //----------------------------------------------------------------
   /**
    * @brief 设置控件的对齐方式与偏移量
    * @param flags [in] 对齐标志（如 WND_ALIGN_LEFT | WND_ALIGN_TOP 表示左上对齐）
    * @param left [in] 左对齐偏移量（像素，仅 WND_ALIGN_LEFT 生效）
    * @param top [in] 上对齐偏移量（像素，仅 WND_ALIGN_TOP 生效）
    * @param right [in] 右对齐偏移量（像素，仅 WND_ALIGN_RIGHT 生效）
    * @param bottom [in] 下对齐偏移量（像素，仅 WND_ALIGN_BOTTOM 生效）
    */
   void              Alignment(const int flags,const int left,const int top,const int right,const int bottom);

   /**
    * @brief 根据父区域调整控件位置与尺寸（基于对齐配置）
    * @param rect [in] 父区域矩形（如父控件或图表窗口的区域）
    * @return bool - 对齐结果：true=成功（位置/尺寸调整完成），false=失败
    */
   virtual bool      Align(const CRect &rect);

   //----------------------------------------------------------------
   // 控件ID：设置与获取唯一标识
   //----------------------------------------------------------------
   /**
    * @brief 设置控件唯一ID
    * @param id [in] 目标ID（建议全局唯一）
    * @return long - 处理结果：固定返回 1（表示ID已设置）
    */
   virtual long      Id(const long id);

   /**
    * @brief 获取控件唯一ID
    * @return long - 控件ID（默认 CONTROLS_INVALID_ID 表示未设置）
    */
   long              Id(void)                          const;

   //----------------------------------------------------------------
   // 控件状态：启用/可见/激活状态操作
   //----------------------------------------------------------------
   /**
    * @brief 检查控件是否启用（可响应事件）
    * @return bool - 启用状态：true=启用，false=禁用
    */
   bool              IsEnabled(void)                   const;

   /**
    * @brief 启用控件（使其可响应事件）
    * @return bool - 操作结果：true=成功（触发 OnEnable()），false=失败（已启用）
    */
   virtual bool      Enable(void);

   /**
    * @brief 禁用控件（使其不响应事件）
    * @return bool - 操作结果：true=成功（触发 OnDisable()），false=失败（已禁用）
    */
   virtual bool      Disable(void);

   /**
    * @brief 检查控件是否可见
    * @return bool - 可见状态：true=可见，false=隐藏
    */
   bool              IsVisible(void)                   const;

   /**
    * @brief 设置控件可见性
    * @param flag [in] 可见状态：true=显示，false=隐藏
    * @return bool - 操作结果：true=成功（调用 Show()/Hide()），false=失败（状态未变）
    */
   virtual bool      Visible(const bool flag);

   /**
    * @brief 显示控件（设置可见状态为 true）
    * @return bool - 操作结果：true=成功（触发 OnShow()），false=失败（已可见）
    */
   virtual bool      Show(void);

   /**
    * @brief 隐藏控件（设置可见状态为 false）
    * @return bool - 操作结果：true=成功（触发 OnHide()），false=失败（已隐藏）
    */
   virtual bool      Hide(void);

   /**
    * @brief 检查控件是否激活（鼠标聚焦）
    * @return bool - 激活状态：true=激活（鼠标在控件内），false=未激活
    */
   bool              IsActive(void)                    const;

   /**
    * @brief 激活控件（设置为鼠标聚焦状态）
    * @return bool - 操作结果：true=成功（触发 OnActivate()），false=失败（已激活）
    */
   virtual bool      Activate(void);

   /**
    * @brief 取消控件激活（失去鼠标聚焦）
    * @return bool - 操作结果：true=成功（触发 OnDeactivate()），false=失败（未激活）
    */
   virtual bool      Deactivate(void);

   //----------------------------------------------------------------
   // 状态标志：直接操作状态位（高级用法）
   //----------------------------------------------------------------
   /**
    * @brief 获取完整状态标志（所有 WND_STATE_FLAG_* 位的组合）
    * @return int - 状态标志值
    */
   int               StateFlags(void)                  const;

   /**
    * @brief 设置完整状态标志（覆盖所有位）
    * @param flags [in] 新的状态标志值（WND_STATE_FLAG_* 的组合）
    */
   void              StateFlags(const int flags);

   /**
    * @brief 置位状态标志（将指定位置为 1，其他位不变）
    * @param flags [in] 要置位的标志（WND_STATE_FLAG_* 的组合）
    */
   void              StateFlagsSet(const int flags);

   /**
    * @brief 复位状态标志（将指定位置为 0，其他位不变）
    * @param flags [in] 要复位的标志（WND_STATE_FLAG_* 的组合）
    */
   void              StateFlagsReset(const int flags);

   //----------------------------------------------------------------
   // 属性标志：直接操作属性位（高级用法）
   //----------------------------------------------------------------
   /**
    * @brief 获取完整属性标志（所有 WND_PROP_FLAG_* 位的组合）
    * @return int - 属性标志值
    */
   int               PropFlags(void)                   const;

   /**
    * @brief 设置完整属性标志（覆盖所有位）
    * @param flags [in] 新的属性标志值（WND_PROP_FLAG_* 的组合）
    */
   void              PropFlags(const int flags);

   /**
    * @brief 置位属性标志（将指定位置为 1，其他位不变）
    * @param flags [in] 要置位的标志（WND_PROP_FLAG_* 的组合）
    */
   void              PropFlagsSet(const int flags);

   /**
    * @brief 复位属性标志（将指定位置为 0，其他位不变）
    * @param flags [in] 要复位的标志（WND_PROP_FLAG_* 的组合）
    */
   void              PropFlagsReset(const int flags);

   //----------------------------------------------------------------
   // 鼠标状态：获取与设置鼠标缓存（高级用法）
   //----------------------------------------------------------------
   /**
    * @brief 获取最后一次鼠标X坐标
    * @return int - 鼠标X坐标（像素）
    */
   int               MouseX(void)                      const;

   /**
    * @brief 设置鼠标X坐标缓存（用于模拟鼠标事件）
    * @param value [in] 鼠标X坐标（像素）
    */
   void              MouseX(const int value);

   /**
    * @brief 获取最后一次鼠标Y坐标
    * @return int - 鼠标Y坐标（像素）
    */
   int               MouseY(void)                      const;

   /**
    * @brief 设置鼠标Y坐标缓存（用于模拟鼠标事件）
    * @param value [in] 鼠标Y坐标（像素）
    */
   void              MouseY(const int value);

   /**
    * @brief 获取最后一次鼠标按键状态
    * @return int - 鼠标状态（MOUSE_* 常量的组合，如 MOUSE_LEFT | MOUSE_SHIFT）
    */
   int               MouseFlags(void)                  const;

   /**
    * @brief 设置鼠标按键状态缓存（用于模拟鼠标事件）
    * @param value [in] 鼠标状态（MOUSE_* 常量的组合）
    */
   virtual void      MouseFlags(const int value);

   /**
    * @brief 取消当前控件的鼠标聚焦（激活状态）
    * @param id [in] 新获取聚焦的控件ID（默认 CONTROLS_INVALID_ID 表示无新聚焦）
    * @return bool - 操作结果：true=成功（已取消聚焦），false=失败（当前控件ID与参数一致）
    */
   bool              MouseFocusKill(const long id=CONTROLS_INVALID_ID);

   /**
    * @brief 将控件置顶（提高显示优先级，确保不被其他控件遮挡）
    * @return bool - 操作结果：true=成功（发送 ON_BRING_TO_TOP 事件），false=失败
    */
   bool              BringToTop(void);

protected:
   //----------------------------------------------------------------
   // 内部事件回调：子类可重写以定制行为（保护，仅子类访问）
   //----------------------------------------------------------------
   /**
    * @brief 控件创建完成后回调（子类重写以初始化具体资源）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnCreate(void);

   /**
    * @brief 控件销毁前回调（子类重写以释放具体资源）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnDestroy(void);

   /**
    * @brief 控件移动后回调（子类重写以更新位置相关资源）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnMove(void);

   /**
    * @brief 控件尺寸变化后回调（子类重写以更新尺寸相关资源）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnResize(void);

   /**
    * @brief 控件启用后回调（子类重写以恢复响应能力）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnEnable(void);

   /**
    * @brief 控件禁用后回调（子类重写以暂停响应能力）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnDisable(void);

   /**
    * @brief 控件显示后回调（子类重写以显示具体内容）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnShow(void);

   /**
    * @brief 控件隐藏后回调（子类重写以隐藏具体内容）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnHide(void);

   /**
    * @brief 控件激活后回调（子类重写以处理聚焦逻辑）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnActivate(void);

   /**
    * @brief 控件取消激活后回调（子类重写以处理失焦逻辑）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnDeactivate(void);

   /**
    * @brief 控件被点击时回调（左键释放时触发）
    * @return bool - 处理结果：true=成功（发送 ON_CLICK 事件），false=失败
    */
   virtual bool      OnClick(void);

   /**
    * @brief 控件被双击时回调（两次点击间隔≤ CONTROLS_DBL_CLICK_TIME）
    * @return bool - 处理结果：true=成功（发送 ON_DBL_CLICK 事件），false=失败
    */
   virtual bool      OnDblClick(void);

   /**
    * @brief 控件内容变化时回调（子类重写以处理状态同步）
    * @return bool - 处理结果：true=成功，false=失败（默认 true）
    */
   virtual bool      OnChange(void);

   //----------------------------------------------------------------
   // 鼠标事件回调：子类可重写以定制鼠标行为（保护，仅子类访问）
   //----------------------------------------------------------------
   /**
    * @brief 鼠标左键按下时回调
    * @return bool - 处理结果：true=成功（触发拖拽或点击预处理），false=失败
    */
   virtual bool      OnMouseDown(void);

   /**
    * @brief 鼠标左键释放时回调
    * @return bool - 处理结果：true=成功（触发点击或双击判断），false=失败
    */
   virtual bool      OnMouseUp(void);

   //----------------------------------------------------------------
   // 拖拽事件回调：子类可重写以定制拖拽行为（保护，仅子类访问）
   //----------------------------------------------------------------
   /**
    * @brief 拖拽开始时回调（鼠标按下且控件支持拖拽）
    * @return bool - 处理结果：true=成功（禁用图表滚动+发送 ON_DRAG_START 事件），false=失败
    */
   virtual bool      OnDragStart(void);

   /**
    * @brief 拖拽过程中回调（鼠标移动且正在拖拽）
    * @param x [in] 当前鼠标X坐标（像素）
    * @param y [in] 当前鼠标Y坐标（像素）
    * @return bool - 处理结果：true=成功（移动控件+更新鼠标缓存），false=失败
    */
   virtual bool      OnDragProcess(const int x,const int y);

   /**
    * @brief 拖拽结束时回调（鼠标释放且正在拖拽）
    * @return bool - 处理结果：true=成功（启用图表滚动+发送 ON_DRAG_END 事件），false=失败
    */
   virtual bool      OnDragEnd(void);

   //----------------------------------------------------------------
   // 拖拽辅助对象：创建与销毁（保护，仅子类访问）
   //----------------------------------------------------------------
   /**
    * @brief 创建拖拽辅助对象（子类重写以实现自定义拖拽效果）
    * @return bool - 创建结果：true=成功，false=失败（默认 false）
    */
   virtual bool      DragObjectCreate(void);

   /**
    * @brief 销毁拖拽辅助对象（释放内存）
    * @return bool - 销毁结果：true=成功（对象已销毁或为空），false=失败
    */
   virtual bool      DragObjectDestroy(void);
  };

//+------------------------------------------------------------------+
//| CDragWnd 类：拖拽辅助类（继承自 CWnd）                            |
//| 核心能力：为控件拖拽提供边界限制功能，确保拖拽过程中控件不超出指定范围 |
//| 适用场景：需要限制拖拽边界的控件（如滚动条滑块、可拖动面板等）       |
//+------------------------------------------------------------------+
class CDragWnd : public CWnd
  {
protected:
   // 拖拽边界限制（保护，仅内部与子类访问）
   int               m_limit_left;          // 左边界限制（拖拽时不能超过此X坐标）
   int               m_limit_top;           // 上边界限制（拖拽时不能超过此Y坐标）
   int               m_limit_right;         // 右边界限制（拖拽时不能超过此X坐标）
   int               m_limit_bottom;        // 下边界限制（拖拽时不能超过此Y坐标）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化拖拽辅助对象默认状态
    * @details 继承 CWnd 构造逻辑，边界限制默认未设置（无限制）
    */
                     CDragWnd(void);

   /**
    * @brief 析构函数：清理拖拽辅助对象资源
    * @details 依赖 CWnd 析构逻辑，无额外资源需释放
    */
                    ~CDragWnd(void);

   //----------------------------------------------------------------
   // 拖拽边界：设置限制范围
   //----------------------------------------------------------------
   /**
    * @brief 设置拖拽时的边界限制（控件不能超出此矩形范围）
    * @param l [in] 左边界限制（X坐标）
    * @param t [in] 上边界限制（Y坐标）
    * @param r [in] 右边界限制（X坐标）
    * @param b [in] 下边界限制（Y坐标）
    */
   void              Limits(const int l,const int t,const int r,const int b);

protected:
   //----------------------------------------------------------------
   // 拖拽过程回调：重写以实现边界限制（保护，仅子类访问）
   //----------------------------------------------------------------
   /**
    * @brief 拖拽过程中回调（带边界限制）
    * @param x [in] 当前鼠标X坐标（像素）
    * @param y [in] 当前鼠标Y坐标（像素）
    * @return bool - 处理结果：true=成功（在限制范围内移动控件+发送事件），false=失败
    * @note 自动调整偏移量，确保控件不超出设置的边界限制
    */
   virtual bool      OnDragProcess(const int x,const int y);
  };
//+------------------------------------------------------------------+